#!/usr/bin/env node

const fs = require('fs')
const path = require('path')
const {execFileSync} = require('child_process')

// Pass a directory containing tree-sitter grammar repos
let searchDir = process.argv[2]
if (!searchDir) {
    console.log('Usage: update <code-directory>')
    process.exit(1)
}

searchDir = path.join(process.cwd(), searchDir)
const filenames = fs.readdirSync(searchDir)

// Examine every directory starting with `tree-sitter-`
for (const filename of filenames) {
    if (!filename.startsWith('tree-sitter-')) continue;
    const repoPath = path.join(searchDir, filename)
    const repoInfoPath = path.join(repoPath, 'package.json');
    if (!fs.existsSync(repoInfoPath)) continue;
    const repoInfo = require(repoInfoPath);
    let info = repoInfo['tree-sitter']
    if (!info) continue
    if (!Array.isArray(info)) info = [info];

    // Examine every "tree-sitter" entry in package.json. Some may have
    // non-default paths (e.g. if one repo contains multiple parsers)
    const parserPaths = new Set(info.map(entry =>
        entry.path ? path.join(repoPath, entry.path) : repoPath
    ))
    for (const parserPath of parserPaths) {
        const grammarName = require(path.join(parserPath, 'src', 'grammar.json')).name
        const wasmName = `tree-sitter-${grammarName}.wasm`

        // If the grammar is included in this repo, then recompile the wasm file
        // from the latest source code.
        if (fs.existsSync(wasmName)) {
            try {
                execFileSync('git', ['diff-index', '--quiet', 'master', '--'], {cwd: repoPath})
            } catch (_) {
                console.log(`${repoPath} has changes or is not on master`)
                continue
            }

            console.log('Building', wasmName, 'in', parserPath, '...');
            execFileSync('tree-sitter', ['build-wasm'], {cwd: parserPath})
            fs.copyFileSync(path.join(parserPath, wasmName), wasmName)
        }
    }
}
